home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 19 / Mac Magazin and MacEasy Magazine CD - Issue 19.iso / Wissenschaft & Technik / BibTeX ƒ / Source code / file-io.cp < prev    next >
Text File  |  1996-02-18  |  25KB  |  510 lines

  1. /**************************************************************************
  2. *                                                                         *
  3. * Product:    Bibtex                                                   *
  4. * Module:     File I/O                                                    *
  5. * File:       file-io.cp                                                  *
  6. * Abstract:   The functions in this module are rough equivalents to Unix  *
  7. *             file I/O functions that Bibtex needs.                    *
  8. * Exports:                                                                *
  9. *             CloseFile                                                   *
  10. *             FPrintF                                                     *
  11. *             FPutC                                                       *
  12. *             FPutS                                                       *
  13. *             GetC                                                        *
  14. *             OpenInputFile                                               *
  15. *             OpenOutputFile                                              *
  16. *             UnGetC                                                      *
  17. * History:                                                                *
  18. *     1.0     11-Jul-95   RJZ.  Initial version.                          *
  19. *                                                                         *
  20. **************************************************************************/
  21. #include "CBibTeXApp.h"
  22. #include "bibutils.h"
  23. #include "BibTeX.h"
  24. #include "file-io.h"
  25. #include <stdarg.h>
  26.  
  27. // Local variables:
  28.  
  29.                                         // Output buffer.
  30. static char gBuffer[kBufferSize];
  31.  
  32. /*************************************************************************
  33. *                                                                        *
  34. * Function:   CloseFile                                                  *
  35. * Purpose:    Closes a file.                                             *
  36. * Inputs:     descPtr is a pointer to a file description structure for   *
  37. *             the file to be closed.                                     *
  38. * Outputs:    None.                                                      *
  39. * Exceptions: Throws an exception if an OS error occurs.                 *
  40. * Side Effects:   Closes a file.                                         *
  41. * Design:     In addition to closing the file, this function also        *
  42. *             flushes the volume that contains the file.  IM recommends  *
  43. *             this.                                                      *
  44. * Errors:     Displays an error message if an OS error occurs.           *
  45. * History:                                                               *
  46. *     1.0     10-Jul-95   RJZ.  Initial version.                         *
  47. *                                                                        *
  48. *************************************************************************/
  49. void CloseFile(FileDescPtr descPtr) {
  50.     OSErr err;
  51.  
  52.     if (descPtr->refNum != 0) {
  53.         err = ::FSClose(descPtr->refNum);
  54.         if (err == noErr)
  55.             err = ::FlushVol(NULL, descPtr->spec.vRefNum);
  56.         descPtr->refNum = 0;
  57.     }
  58. //    if (err != noErr) {
  59. //        FatalOSErr("Problem closing file %s: %s",
  60. //                    (char *) descPtr->spec.name + 1, err);
  61. //    }
  62.     delete descPtr;
  63. }
  64.  
  65. /**************************************************************************
  66. *                                                                         *
  67. * Function:   FPrintF                                                     *
  68. * Purpose:    Performs formatted I/O to a file.  It is the same as        *
  69. *             fprintf.                                                    *
  70. * Inputs:     descPtr is a pointer to a file description structure, and   *
  71. *             format is a pointer to a format string.  Zero or more       *
  72. *             arguments may follow.                                       *
  73. * Outputs:    The number of bytes written.                                *
  74. * Exceptions: Throws an exception if a write error occurs.                *
  75. * Side Effects:   Writes to a file.                                       *
  76. * Design:     Out of the box, Bibtex uses fprintf to format and print  *
  77. *             error messages.  Here I use vsprintf to format the message  *
  78. *             and then Macintosh file I/O to write the message.  As a     *
  79. *             result, this function behaves just like fprintf.            *
  80. * Errors:     Checks for I/O errors as a result of the call to FSWrite.   *
  81. * History:                                                                *
  82. *     1.0     11-Jul-95   RJZ.  Initial version.                          *
  83. *                                                                         *
  84. **************************************************************************/
  85. long FPrintF(FileDescPtr descPtr, const char *format, ...) {
  86.     va_list args;                       // variable argument list
  87.     long    count;
  88.     OSErr   err;
  89.  
  90.     va_start(args, format);
  91.     count = vsprintf(gBuffer, format, args);
  92.     va_end(args);
  93.     if (count > kBufferSize)
  94.         FPrintFStdErr("Wrote past end of buffer in FPrintF!\r");
  95.     err = ::FSWrite(descPtr->refNum, &count, gBuffer);
  96.     if (err != noErr)
  97.         FatalOSErr("Error while writing to %s: %s",
  98.                    (char *) descPtr->spec.name + 1, err);
  99.     return count;
  100. }
  101.  
  102. /*************************************************************************
  103. *                                                                        *
  104. * Function:   FPrintFStdErr                                              *
  105. * Purpose:    This function is the equivalent of calling fprintf with    *
  106. *             the output directed to stderr.  In this case we send the   *
  107. *             output to the log window.                                  *
  108. * Inputs:     The inputs are the same as for printf.                     *
  109. * Outputs:    The function value is the number of characters displayed.  *
  110. * Exceptions: None.                                                      *
  111. * Side Effects:   Displays characters on the screen.                     *
  112. * Errors:     None.                                                      *
  113. * History:                                                               *
  114. *     1.0     29-Jul-95   RJZ.  Initial version.                         *
  115. *                                                                        *
  116. *************************************************************************/
  117. long FPrintFStdErr(const char *format, ...) {
  118.     va_list args;                       // variable argument list
  119.     long    count;
  120.  
  121.     va_start(args, format);
  122.     count = vsprintf(gBuffer, format, args);
  123.     va_end(args);
  124.     CBibtexApp::DisplayInLogWindow(gBuffer, count);
  125.  
  126.     return count;
  127. }
  128.  
  129. /************************************************************************
  130. *                                                                       *
  131. * Function:   FPutC                                                     *
  132. * Purpose:    Writes a character to a file.                             *
  133. * Inputs:     mess1 is the character to be written.  descPtr points to  *
  134. *             the file where the character will be written.             *
  135. * Outputs:    None.                                                     *
  136. * Exceptions: Throws an exception if an error occurs.                   *
  137. * Side Effects:   Writes to a file.                                     *
  138. * Design:     This function mimics the behavior of the Unix function    *
  139. *             fputc() except that it doesn't have a return value.       *
  140. *             Instead, if an error occurs, it throws an exception.      *
  141. * Errors:     Checks for OS errors from the call to FSWrite.            *
  142. * History:                                                              *
  143. *     1.0     12-Jul-95   RJZ.  Initial version.                        *
  144. *                                                                       *
  145. ************************************************************************/
  146. void FPutC(const char mess1, FileDescPtr descPtr) {
  147.     if(descPtr == 0 ) {
  148.         FPutC(mess1);
  149.         return;
  150.     }
  151.         
  152.     long    count;
  153.     OSErr   err;
  154.     
  155.     count = 1;
  156.     #if 1
  157.     err = ::FSWrite(descPtr->refNum, &count, &mess1);
  158.     #else
  159.     // attempt to use async write, but I get illegal instruction problems!
  160.     IOParam bib_pb; // must be set up elsewhere
  161.     bib_pb.ioVRefNum = descPtr->spec.vRefNum;    // as union member field
  162.     bib_pb.ioRefNum = descPtr->refNum;    // as union member field
  163.     bib_pb.ioPosMode = fsAtMark; // from wherever
  164.     bib_pb.ioReqCount = 1;    // the line size
  165.     char printchar = mess1;
  166.     bib_pb.ioBuffer = &printchar;        // the one character
  167.     err = PBWriteAsync((ParamBlockRec*) &bib_pb);    // write one char
  168.     #endif
  169.     
  170.     if (err != noErr)
  171.         FatalOSErr("Error while writing to %s: %s",
  172.                     (char *) descPtr->spec.name + 1, err);
  173. }
  174.  
  175. /************************************************************************
  176. *                                                                       *
  177. * Function:   FPutC                                                     *
  178. * Purpose:    Writes a character to a file.                             *
  179. * Inputs:     mess1 is the character to be written.  descPtr points to  *
  180. *             the file where the character will be written.             *
  181. * Outputs:    None.                                                     *
  182. * Exceptions: Throws an exception if an error occurs.                   *
  183. * Side Effects:   Writes to a file.                                     *
  184. * Design:     This function mimics the behavior of the Unix function    *
  185. *             fputc() except that it doesn't have a return value.       *
  186. *             Instead, if an error occurs, it throws an exception.      *
  187. * Errors:     Checks for OS errors from the call to FSWrite.            *
  188. * History:                                                              *
  189. *     1.0     12-Jul-95   VMD.  Initial version.                        *
  190. *                                                                       *
  191. ************************************************************************/
  192. void FPutC(const char mess1) {
  193.     long    count = 1;
  194.  
  195.     gBuffer[0] = mess1;
  196.     gBuffer[1] = '\0';
  197.     CBibtexApp::DisplayInLogWindow(gBuffer, count);
  198. }
  199.  
  200. /*************************************************************************
  201. *                                                                        *
  202. * Function:   FPutS                                                      *
  203. * Purpose:    Writes a character string to a file.                       *
  204. * Inputs:     mess1 is the string to be written.  descPtr points to the  *
  205. *             file where the string will be written.                     *
  206. * Outputs:    None.                                                      *
  207. * Exceptions: Throws an exception if an OS error occurs.                 *
  208. * Side Effects:   Writes to a file.                                      *
  209. * Design:     This function mimics the behavior of the Unix function     *
  210. *             fputs() except that it doesn't have a return value.        *
  211. *             Instead, it an error occurs, it throws an exception.       *
  212. * Errors:     Checks for OS errors from the call to FSWrite.             *
  213. * History:                                                               *
  214. *     1.0     12-Jul-95   RJZ.  Initial version.                         *
  215. *                                                                        *
  216. *************************************************************************/
  217. void FPutS(const char *mess1, FileDescPtr descPtr) {
  218.     long    count;
  219.     OSErr   err;
  220.  
  221.     count = strlen(mess1);
  222.     err = ::FSWrite(descPtr->refNum, &count, mess1);
  223.     if (err != noErr)
  224.         FatalOSErr("Error while writing to %s: %s",
  225.                     (char *) descPtr->spec.name + 1, err);
  226. }
  227.  
  228. /**************************************************************************
  229. *                                                                         *
  230. * Function:   FSeek                                                       *
  231. * Purpose:    Changes the position of the file mark.                      *
  232. * Inputs:     descPtr is a pointer to the file description structure for  *
  233. *             the file, offset is how much to change the file mark, and   *
  234. *             "from" indicates how to do the change.                      *
  235. * Outputs:    Returns any OS error that occurs.                           *
  236. * Exceptions: None.                                                       *
  237. * Side Effects:   Moves the file mark.                                    *
  238. * Design:     This function is designed to mimic the behavior of the      *
  239. *             Unix fseek() function.  Use from = 0 if the offset is from  *
  240. *             the start of the file, 1 if the offset is from the current  *
  241. *             mark, and 2 if the offset is from the end of file.  If      *
  242. *             some other (invalid) value is specified, assume that        *
  243. *             offset is from current mark.                                *
  244. * Errors:     Returns any OS error that occurs because fseek() returns a  *
  245. *             non-zero value if an error occurs.                          *
  246. * History:                                                                *
  247. *     1.0     10-Jul-95   RJZ.  Initial version.                          *
  248. *                                                                         *
  249. **************************************************************************/
  250. OSErr FSeek(FileDescPtr descPtr, long offset, short from) {
  251.     OSErr   err;
  252.  
  253.                                         // Translate the meaning of "from" from
  254.                                         // its Unix sense to the Macintosh
  255.                                         // equivalent.
  256.     switch (from) {
  257.     case 0:
  258.         from = fsFromStart;
  259.         break;
  260.     case 1:
  261.         from = fsFromMark;
  262.         break;
  263.     case 2:
  264.         from = fsFromLEOF;
  265.         break;
  266.     default:
  267.         from = fsAtMark;
  268.     }
  269.     err = ::SetFPos(descPtr->refNum, from, offset);
  270.  
  271.     return err;
  272. }
  273.  
  274. /**************************************************************************
  275. *                                                                         *
  276. * Function:   GetC                                                        *
  277. * Purpose:    Reads a character from a file.                              *
  278. * Inputs:     descPtr is a pointer to the file description structure for  *
  279. *             the file.                                                   *
  280. * Outputs:    The function value is a character returned in a long.       *
  281. * Exceptions: Throws an exception if a read error other than an eof       *
  282. *             occurs.                                                     *
  283. * Side Effects:   Advances position in file.                              *
  284. * Design:     This function is designed to work like the Unix getc()      *
  285. *             function.  That's why it has to return the character it     *
  286. *             reads as a long.  Otherwise, there's no way to return EOF.  *
  287. * Errors:     Posts an alert if an error other that eof occurs.           *
  288. * History:                                                                *
  289. *     1.0     10-Jul-95   RJZ.  Initial version.                          *
  290. *                                                                         *
  291. **************************************************************************/
  292. long GetC(FileDescPtr descPtr) {
  293.     char    c;
  294.     long    count;
  295.     OSErr   err;
  296.  
  297.     count = 1;
  298.     err = ::FSRead(descPtr->refNum, &count, &c);
  299.     if (err != noErr) {
  300.         if (err == eofErr)
  301.             return EOF;
  302.         else
  303.             FatalOSErr("Error reading from file %s: %s",
  304.                         (char *) descPtr->spec.name + 1, err);
  305.     }
  306.     return (unsigned char) c;
  307. }
  308.  
  309. /**************************************************************************
  310. *                                                                         *
  311. * Function:   OpenInputFile                                               *
  312. * Purpose:    Opens an input file for reading.                            *
  313. * Inputs:     descPtr is a pointer to the FileDesc structure of the file  *
  314. *             to be opened.                                               *
  315. * Outputs:    Stuffs the file reference number into the FileDesc          *
  316. *             structure.                                                  *
  317. * Exceptions: Throws an exception if unable to open the file.             *
  318. * Side Effects:   Opens a file.                                           *
  319. * Design:     Originally this was to be an equivalent to the Unix         *
  320. *             open().  However, it's hard to produce an exact equivalent  *
  321. *             to this function on the Macintosh.  For example, open()     *
  322. *             creates a file if it doesn't exist.  That's why I didn't    *
  323. *             give this function a name that was similar to open().       *
  324. * Errors:     Displays a message if unable to open the file.              *
  325. * History:                                                                *
  326. *     1.0     10-Jul-95   Initial version.                                *
  327. *                                                                         *
  328. **************************************************************************/
  329. void OpenInputFile(FileDescPtr descPtr) {
  330.     OSErr   err;
  331.  
  332.     err = ::FSpOpenDF(&descPtr->spec, fsRdPerm, &descPtr->refNum);
  333.     if (err != noErr)
  334.         FatalOSErr("Problem opening file %s: %s",
  335.                     (char *) descPtr->spec.name + 1, err);
  336. }
  337.  
  338. /**************************************************************************
  339. *                                                                         *
  340. * Function:   OpenOutputFile                                              *
  341. * Purpose:    Opens an output file for writing.                           *
  342. * Inputs:     descPtr is a pointer to the FileDesc structure of the file  *
  343. *             to be opened.                                               *
  344. * Outputs:    Stuffs the file reference number into the FileDesc          *
  345. *             structure.                                                  *
  346. * Exceptions: Throws an exception if unable to open the file.             *
  347. * Side Effects:   Opens a file.                                           *
  348. * Design:     Originally this was to be an equivalent to the Unix         *
  349. *             open().  However, it's hard to produce an exact equivalent  *
  350. *             to this function on the Macintosh.  For example, open()     *
  351. *             creates a file if it doesn't exist.  That's why I didn't    *
  352. *             give this function a name that was similar to open().       *
  353. * Errors:     Displays a message if unable to open the file.              *
  354. * History:                                                                *
  355. *     1.0     10-Jul-95   Initial version.                                *
  356. *                                                                         *
  357. **************************************************************************/
  358. void OpenOutputFile(FileDescPtr descPtr) {
  359.     OSErr   err;
  360.  
  361.     err = ::FSpOpenDF(&descPtr->spec, fsWrPerm, &descPtr->refNum);
  362.     if (err != noErr)
  363.         FatalOSErr("Problem opening file %s: %s",
  364.                     (char *) descPtr->spec.name + 1, err);
  365. }
  366.  
  367. /**************************************************************************
  368. *                                                                         *
  369. * Function:   UnGetC                                                      *
  370. * Purpose:    Puts back a character that was just read.                   *
  371. * Inputs:     ch is the character just read and descPtr is a pointer to   *
  372. *             the file description structure.                             *
  373. * Outputs:    noErr if successful, EOF if unsuccessful or if ch is EOF.   *
  374. * Exceptions: None.                                                       *
  375. * Side Effects:   Moves the file mark.                                    *
  376. * Design:     This works like the Unix function ungetc().  Note that      *
  377. *             this function will not work for the idx file since the      *
  378. *             input for that file is buffered.  If it becomes necessary   *
  379. *             to use UnGetC() on the idx file in the future, it           *
  380. *             will be necessary to stop using buffered input for the idx  *
  381. *             file or maybe it will be necessary to create a special      *
  382. *             version of this function for the idx file.                  *
  383. * Errors:     None.                                                       *
  384. * History:                                                                *
  385. *     1.0     10-Jul-95   RJZ.  Initial version.                          *
  386. *                                                                         *
  387. **************************************************************************/
  388. int UnGetC(int ch, FileDescPtr descPtr) {
  389.     OSErr   err;
  390.  
  391.     if (ch != EOF) {
  392.         err = ::SetFPos(descPtr->refNum, fsFromMark, -1L);
  393.         if (err == noErr)
  394.             return noErr;
  395.         else
  396.             return EOF;
  397.     } else
  398.         return EOF;
  399. }
  400.  
  401. boolean    FEof(FileDescPtr descPtr) {
  402.     long end;
  403.     GetEOF(descPtr->refNum, &end);
  404.     long curr;
  405.     GetFPos(descPtr->refNum, &curr);
  406.  
  407.     return (end == curr);
  408. }
  409.  
  410. // not static because it needs to be reset each run.
  411. FileDescPtr myBufferedFile;
  412.  
  413. long GetBibtexCharacter(FileDescPtr descPtr) {
  414.     static short    bufferPos;          // next char to come out of readBuffer
  415.     long            count;              // number of characters to read
  416.     OSErr           err;                // error code
  417.     static char     readBuffer[kReadBufferSize];
  418.     extern FileDescPtr myBufferedFile;
  419.     static short myFileEnd;
  420.     static long myFilePos;
  421.     
  422.     if(myBufferedFile != descPtr)  {
  423.         // move pos in old file
  424.         if(myBufferedFile)
  425.             SetFPos(myBufferedFile->refNum,fsFromStart, myFilePos);
  426.         // do new file
  427.         myBufferedFile = descPtr;
  428.         bufferPos = 0;
  429.         myFileEnd = -1;
  430.         GetFPos(myBufferedFile->refNum, &myFilePos);
  431.     }
  432.     
  433.     if(bufferPos == myFileEnd){
  434.         // now we really are at the end
  435.         long end;
  436.         GetEOF(myBufferedFile->refNum, &end);
  437.         SetFPos(myBufferedFile->refNum, fsFromStart, end);
  438.         return EOF;
  439.     }
  440.     
  441.     if(bufferPos % kReadBufferSize == 0)  {
  442.         count = kReadBufferSize;
  443.         err = ::FSRead(descPtr->refNum, &count, readBuffer);
  444.         if (err != noErr) {
  445.             if(err == eofErr)  {
  446.                 myFileEnd = count;
  447.                 // pretend we're not at the end yet
  448.                 SetFPos(myBufferedFile->refNum, fsFromLEOF, -2);
  449.             } else {
  450.                 FatalOSErr("Error while reading %s: %s", (char*) myBufferedFile->spec.name, err);
  451.             }
  452.         }
  453.         bufferPos = 0;
  454.     }
  455.     myFilePos++;
  456.     
  457.     return readBuffer[bufferPos++];
  458. }
  459.  
  460.  
  461. #define EOL 13    // line delimiter is CR (ASCII 13)
  462.  
  463. /*
  464.     ReadLine reads a line of text from the file represented by pbp.
  465.     It returns -1 if the file is not delimited, or a file manager
  466.     result code (i.e. eofErr.) It places the null terminated string
  467.     in the buffer pointed to by lineBuf.
  468. */
  469.  
  470. /*
  471. IOParam bib_pb; // must be set up elsewhere
  472. extern char* buffer;
  473.  
  474. void ReadLine(FileDescPtr descPtr) // fixed:, char *lineBuf, const int size)
  475. {    
  476.     extern long last; // BibTeX uses this to keep track of how much was read
  477.     bib_pb.ioVRefNum = descPtr->spec.vRefNum;    // as union member field
  478.     bib_pb.ioRefNum = descPtr->refNum;    // as union member field
  479.  
  480.     OSErr rc = PBReadSync((ParamBlockRec*) &bib_pb);    // read one line
  481.     last = bib_pb.ioActCount;
  482.     
  483.     if (rc==eofErr && last==0){
  484.         return;        // end of file reached
  485.     }
  486.     
  487.     if ((rc==noErr) || (rc==eofErr)) {
  488.         if (last==bufsize) {
  489.             short in = buffer[last-1];
  490.             // skip past eoln if buffer full
  491.             while (in != EOF && in != EOL )
  492.                 in = GetC(descPtr);
  493.             return;    // not a delimited file
  494.         }
  495.         if (buffer[last-1] == EOL) // last line has no EOL
  496.             last--;    
  497.     }
  498.  
  499. }
  500.  
  501. */
  502.       // for speed in the crucial readline routine, we set these up once only
  503.     /* These would have to be put somewhere if we used the above routine
  504.     extern IOParam bib_pb;
  505.     bib_pb.ioPosMode = fsAtMark | 0x80 | (256*13); // just read a line; EOL = 13
  506.     bib_pb.ioReqCount = bufsize;    // max line size
  507.     bib_pb.ioBuffer = buffer;        // transfer to this address
  508.     */
  509.  
  510.